package com.sun.weight;

import lombok.Data;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 非平滑加权轮询负载均衡算法实现
 * 这种算法按照权重比例分配请求，但分配不够平滑
 */

public class SmoothWeightedRoundRobin {

    // 服务器节点类
    @Data
    public static class Server {
        private String name;
        private int weight;
        private int currentWeight;

        public Server(String name, int weight, int currentWeight) {
            this.name = name;
            this.weight = weight;
            this.currentWeight = currentWeight;
        }

    }

    private List<Server> servers; // 服务器列表
    private int totalWeight;      // 总权重
    private AtomicInteger currentIndex; // 当前索引

    public SmoothWeightedRoundRobin() {
        servers = new ArrayList<>();
        totalWeight = 0;
        currentIndex = new AtomicInteger(-1);
    }

    /**
     * 添加服务器
     *
     * @param name   服务器名称
     * @param weight 服务器权重
     */
    public void addServer(String name, int weight) {
        if (weight <= 0) {
            throw new IllegalArgumentException("权重必须大于0");
        }
        servers.add(new Server(name, weight, 0));
        totalWeight += weight;
    }

    /**
     * 获取下一台服务器 - 平滑加权轮询算法
     * 算法原理：
         1、每个服务器有两个权重：固定权重(weight)和当前权重(current_weight)
         2、每次选择时，所有服务器的当前权重增加其固定权重
         3、选择当前权重最大的服务器
         4、被选中的服务器的当前权重减去总权重
         5、重复上述过程
     *
     * @return 被选中的服务器
     */
    public Server getNextServer() {
        if (servers.isEmpty()) {
            throw new IllegalStateException("没有可用的服务器");
        }

        for (Server server : servers) {
            server.setCurrentWeight(server.getCurrentWeight() + server.getWeight());
        }

        Server targetServer = null;
        // 遍历服务器列表，找到对应的服务器
        for (Server server : servers) {
            if (targetServer==null){
                targetServer=server;
                continue;
            }
            if (server.currentWeight > targetServer.getCurrentWeight()) {
                targetServer = server;
            }
        }

        if (targetServer != null) {
            targetServer.currentWeight -= totalWeight;
            return targetServer;
        }

        // 正常情况下不会执行到这里
        return servers.get(0);
    }

    /**
     * 打印服务器列表和权重信息
     */
    public void printServerInfo() {
        System.out.println("服务器列表:");
        for (Server server : servers) {
            System.out.println("  " + server.getName() + " - 权重: " + server.getWeight());
        }
        System.out.println("总权重: " + totalWeight);
    }

    /**
     * 测试方法
     */
    public static void main(String[] args) {
        // 创建负载均衡器
        SmoothWeightedRoundRobin lb = new SmoothWeightedRoundRobin();

        // 添加服务器及其权重
        lb.addServer("ServerA", 5); // 50%的请求
        lb.addServer("ServerB", 3); // 30%的请求
        lb.addServer("ServerC", 2); // 20%的请求

        // 打印服务器信息
        lb.printServerInfo();

        // 模拟20次请求分配
        System.out.println("\n请求分配情况:");
        for (int i = 0; i < 20; i++) {
            Server server = lb.getNextServer();
            System.out.println("请求 " + (i + 1) + " 分配给: " + server.getName());
        }

        // 验证分配比例
        System.out.println("\n验证分配比例:");
        int[] count = new int[3]; // 统计每个服务器的请求次数
        for (int i = 0; i < 10000; i++) {
            Server server = lb.getNextServer();
            if ("ServerA".equals(server.getName())) {
                count[0]++;
            } else if ("ServerB".equals(server.getName())) {
                count[1]++;
            } else if ("ServerC".equals(server.getName())) {
                count[2]++;
            }
        }

        System.out.println("ServerA: " + count[0] + " 次 (" + (count[0] / 100.0) + "%)");
        System.out.println("ServerB: " + count[1] + " 次 (" + (count[1] / 100.0) + "%)");
        System.out.println("ServerC: " + count[2] + " 次 (" + (count[2] / 100.0) + "%)");
    }
}